﻿using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace System.Drawing {

	/// <summary>
	/// A set of extensions for the <see cref="Image"/> class.
	/// </summary>
	public static class ImageExtensions {
		/// <summary>
		/// 	Constrains the proportions.
		/// </summary>
		/// <param name = "imgPhoto">The img photo.</param>
		/// <param name = "size">The size.</param>
		/// <param name = "dimension">The dimension.</param>
		/// <returns></returns>
		public static Image ResizeConstrainProportions ( this Image imgPhoto , int size , Dimensions dimension ) {
			if ( dimension == Dimensions.Width && imgPhoto.Width <= size ) {
				var image2 = new Bitmap ( imgPhoto );
				return image2;
			}

			if ( dimension == Dimensions.Height && imgPhoto.Height <= size ) {
				var image2 = new Bitmap ( imgPhoto );
				return image2;
			}

			float num7;
			int width = imgPhoto.Width;
			int height = imgPhoto.Height;
			const int X = 0;
			const int Y = 0;
			const int NUM5 = 0;
			const int NUM6 = 0;

			if ( dimension == Dimensions.Width ) {
				num7 = ( size ) / ( ( float ) width );
			}
			else {
				num7 = ( size ) / ( ( float ) height );
			}

			int num8 = ( int ) ( width * num7 );
			int num9 = ( int ) ( height * num7 );

			if ( num8 <= 0 ) {
				num8 = 400;
			}
			if ( num9 <= 0 ) {
				num9 = 300;
			}

			Bitmap image = new Bitmap ( num8 , num9 , PixelFormat.Format24bppRgb );
			image.SetResolution ( imgPhoto.HorizontalResolution , imgPhoto.VerticalResolution );
			using ( Graphics graphics = Graphics.FromImage ( image ) ) {
				graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
				graphics.DrawImage ( imgPhoto , new Rectangle ( NUM5 , NUM6 , num8 , num9 ) , new Rectangle ( X , Y , width , height ) , GraphicsUnit.Pixel );
			}
			return image;
		}

		/// <summary>
		/// 	Fixeds the size.
		/// </summary>
		/// <param name = "imgPhoto">The img photo.</param>
		/// <param name = "Width">The width.</param>
		/// <param name = "Height">The height.</param>
		/// <param name = "backGroundColor">Color of the back ground.</param>
		/// <returns></returns>
		public static Image ResizeFixedSize ( this Image imgPhoto , int Width , int Height , Color backGroundColor ) {
			float num7;
			int width = imgPhoto.Width;
			int height = imgPhoto.Height;
			const int X = 0;
			const int Y = 0;
			int num5 = 0;
			int num6 = 0;
			float num8 = ( Width ) / ( ( float ) width );
			float num9 = ( Height ) / ( ( float ) height );
			if ( num9 < num8 ) {
				num7 = num9;
				num5 = ( int ) ( ( Width - ( width * num7 ) ) / 2f );
			}
			else {
				num7 = num8;
				num6 = ( int ) ( ( Height - ( height * num7 ) ) / 2f );
			}
			int num10 = ( int ) ( width * num7 );
			int num11 = ( int ) ( height * num7 );
			Bitmap image = new Bitmap ( Width , Height , PixelFormat.Format24bppRgb );
			image.SetResolution ( imgPhoto.HorizontalResolution , imgPhoto.VerticalResolution );
			using ( Graphics graphics = Graphics.FromImage ( image ) ) {
				graphics.Clear ( backGroundColor );
				graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
				graphics.DrawImage ( imgPhoto , new Rectangle ( num5 , num6 , num10 , num11 ) , new Rectangle ( X , Y , width , height ) , GraphicsUnit.Pixel );

				return image;
			}
		}

		/// <summary>
		/// 	Scales the by percent.
		/// </summary>
		/// <param name = "imgPhoto">The img photo.</param>
		/// <param name = "percent">The percent.</param>
		/// <returns></returns>
		public static Image ResizeScaleByPercent ( this Image imgPhoto , int percent ) {
			float num = ( percent ) / 100f;
			int width = imgPhoto.Width;
			int height = imgPhoto.Height;
			const int x = 0;
			const int y = 0;
			const int num6 = 0;
			const int num7 = 0;
			int num8 = ( int ) ( width * num );
			int num9 = ( int ) ( height * num );
			Bitmap image = new Bitmap ( num8 , num9 , PixelFormat.Format24bppRgb );
			image.SetResolution ( imgPhoto.HorizontalResolution , imgPhoto.VerticalResolution );
			using ( Graphics graphics = Graphics.FromImage ( image ) ) {
				graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
				graphics.DrawImage ( imgPhoto , new Rectangle ( num6 , num7 , num8 , num9 ) , new Rectangle ( x , y , width , height ) , GraphicsUnit.Pixel );
				return image;
			}
		}

		/// <summary>
		/// 	Scales the size of the by max.
		/// </summary>
		/// <param name = "imgPhoto">The img photo.</param>
		/// <param name = "width">The width.</param>
		/// <param name = "height">The height.</param>
		/// <param name = "path2Save">The path2 save.</param>
		/// <param name = "overwrite">if set to <c>true</c> [overwrite].</param>
		/// <param name = "format">The format.</param>
		/// <returns></returns>
		public static Image ResizeScaleByMaxSize ( this Image imgPhoto , int width , int height , string path2Save , bool overwrite , ImageFormat format ) {
			//resize immagine
			int widthOld = imgPhoto.Width;
			int heightOld = imgPhoto.Height;

			float fx = widthOld / width;
			float fy = heightOld / height;

			// must fit in thumbnail size
			float f = Math.Max ( fx , fy );
			if ( f < 1 ) {
				f = 1;
			}
			int widthThumb = ( int ) ( widthOld / f );
			int heightThumb = ( int ) ( heightOld / f );

			//se l'immagine è alta o larga 1 pixel, mi ritorna zero quindi al minimo la creo da 1*1 px
			if ( widthThumb == 0 ) {
				widthThumb = 1;
			}

			if ( heightThumb == 0 ) {
				heightThumb = 1;
			}

			return new Bitmap ( imgPhoto , widthThumb , heightThumb );
		}

		/// <summary>
		/// 	Crops the image.
		/// </summary>
		/// <param name = "imgPhoto">The img photo.</param>
		/// <param name = "width">The width.</param>
		/// <param name = "height">The height.</param>
		/// <param name = "cropPosition">The crop position.</param>
		/// <param name = "format">The format.</param>
		/// <returns></returns>
		public static Image ResizeCropImage ( this Image imgPhoto , int width , int height , CropPosition cropPosition , ImageFormat format ) {
			imgPhoto = imgPhoto.Width >= imgPhoto.Height
						? ResizeConstrainProportions ( imgPhoto , height , Dimensions.Height )
						: ResizeConstrainProportions ( imgPhoto , width , Dimensions.Width );

			int xPosition , yPosition;

			switch ( cropPosition ) {
				case CropPosition.BottomCenter: {
					xPosition = ( int ) Math.Round ( ( ( imgPhoto.Width / 2D ) - ( width / 2 ) ) );
					yPosition = imgPhoto.Height - height;
					break;
				}
				case CropPosition.BottomLeft: {
					xPosition = 0;
					yPosition = imgPhoto.Height - height;
					break;
				}
				case CropPosition.BottomRigth: {
					xPosition = imgPhoto.Width - width;
					yPosition = imgPhoto.Height - height;
					break;
				}
				case CropPosition.Center: {
					xPosition = ( int ) Math.Round ( ( ( imgPhoto.Width / 2D ) - ( width / 2 ) ) );
					yPosition = ( int ) Math.Round ( ( ( imgPhoto.Height / 2D ) - ( height / 2 ) ) );

					break;
				}
				case CropPosition.MiddleLeft: {
					xPosition = ( int ) Math.Round ( ( ( imgPhoto.Height / 2D ) - ( height / 2 ) ) );
					yPosition = 0;
					break;
				}
				case CropPosition.MiddleRigth: {
					yPosition = ( int ) Math.Round ( ( ( imgPhoto.Height / 2D ) - ( height / 2 ) ) );
					xPosition = imgPhoto.Width - width;
					break;
				}
				case CropPosition.TopCenter: {
					xPosition = ( int ) Math.Round ( ( ( imgPhoto.Width / 2D ) - ( width / 2 ) ) );
					yPosition = 0;
					break;
				}
				case CropPosition.TopLeft: {
					xPosition = 0;
					yPosition = 0;
					break;
				}
				case CropPosition.TopRigth: {
					xPosition = imgPhoto.Width - width;
					yPosition = 0;
					break;
				}
				default: {
					xPosition = ( int ) Math.Round ( ( ( imgPhoto.Width / 2D ) - ( width / 2 ) ) );
					yPosition = ( int ) Math.Round ( ( ( imgPhoto.Height / 2D ) - ( height / 2 ) ) );

					break;
				}
			}

			Bitmap newImage = new Bitmap ( width , height , PixelFormat.Format24bppRgb );

			newImage.SetResolution ( 92 , 92 );

			using ( Graphics gr = Graphics.FromImage ( newImage ) ) {
				gr.SmoothingMode = SmoothingMode.AntiAlias;
				gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
				gr.PixelOffsetMode = PixelOffsetMode.HighQuality;

				gr.DrawImage ( imgPhoto ,
							   new Rectangle ( 0 , 0 , width , height ) ,
							   new Rectangle ( xPosition , yPosition , width , height ) ,
							   GraphicsUnit.Pixel );

				return newImage;
			}
		}
	}

	/// <summary>
	/// This enums contains the available image dimensions
	/// </summary>
	public enum Dimensions {
		/// <summary>
		/// The width of the image.
		/// </summary>
		Width ,
		/// <summary>
		/// The height of the image.
		/// </summary>
		Height
	}

	/// <summary>
	/// Contains the crop position of the image.
	/// </summary>
	public enum CropPosition {
		
		/// <summary>
		/// The crop of the image will be centered.
		/// </summary>
		Center = 0 ,

		/// <summary>
		/// The crop will start from top-left corner.
		/// </summary>
		TopLeft = 1 ,

		/// <summary>
		/// The crop will start from top-center edge.
		/// </summary>
		TopCenter = 2 ,

		/// <summary>
		/// The crop will start from top-right corner.
		/// </summary>
		TopRigth = 3 ,

		/// <summary>
		/// The crop will start from middle-left edge.
		/// </summary>
		MiddleLeft = 4 ,

		/// <summary>
		/// The crop will start from middle-right edge.
		/// </summary>
		MiddleRigth = 5 ,

		/// <summary>
		/// The crop will start from bottom-left corner.
		/// </summary>
		BottomLeft = 6 ,

		/// <summary>
		/// The crop will start from bottom-center edge.
		/// </summary>
		BottomCenter = 7 ,

		/// <summary>
		/// The crop will start from bottom-right corner.
		/// </summary>
		BottomRigth
	}
}